Swift3.0対応!Google Apps APIを使うためにGoogleサインインを組み込む方法
はじめに
GoogleAppsとは、皆様ご存知のGmailやGoogleカレンダー、Googleドライブなどのクラウドグループウェアツールです。
GoogleAppsにはそれらの機能を使うためのGoogleAppsAPIが公開されています。
GoogleAppsAPIを使うとGmailやGoogleカレンダーなどのデータを取得することが出来ます。
これらのAPIをアプリから使うにはGoogleにサインインをする必要があります *1。
今回はそんなGoogleAppsAPIを使うためにiOSアプリにGoogleサインインを組み込む方法になります。
環境
今回実施している環境は下記の通りです。
XCode | 8.0 |
---|---|
Swift | 3.0 |
CocoaPods | 1.0.0 |
iOS SDK | 9.0 以上 |
準備
1. プロジェクトの作成
まずはXCodeでプロジェクトを新規に作成します。
今回はGoogleSignInSampleというプロジェクトを作成しました。
そしてBundle Identifierの値は設定で使うのでメモしておきましょう。
そして、CocoaPodsで'Google/SignIn'をインストールします。
use_frameworks! target 'GoogleSignInSample' pod 'Google/SignIn'
プロジェクトを作成して'Google/SignIn'をインストールしたらGoogle側の設定になります。
2. Google側の設定
作成したプロジェクトでGoogleログインが使えるように設定します。
ブラウザで下記URLにアクセスします。
https://developers.google.com/identity/sign-in/ios/start
表示された画面に従って設定をします。
Swiftを選択します。
下記はサンプルプロジェクトのダウンロードが出来るコマンドなので必要に応じて取得して下さい。(無くても大丈夫です)
> pod try Google
GET A CONFIGURATION FILE ボタンをクリックする
アプリケーションプロジェクトの登録
GET A CONFIGURATION FILE ボタンをクリックすると「Create or choose an app」ページが表示されます。
① App name には今回のアプリ名を、
② iOS Bundle ID には、プロジェクトの作成時にメモしたBundle Identifierの値を入力します。
入力したら下の Choose and configure services → ボタンをクリックしましょう。
Googleサインインの有効化
アプリケーションの登録が成功したら、今度はサインインを有効化します。
Google Sign-In を選択し、ENABLE GOOGLE SIGN-IN ボタンをクリックします。
有効化されると下記表示になります。
設定ファイル(GoogleService-Info.plist)をダウンロードする画面に遷移するために、
Generate configuration files → ボタンをクリックします。
GoogleService-Info.plistのダウンロード
下記画面が表示されたら、Download GoogleService-Info.plist ボタンをクリックして、GoogleService-Info.plistファイルをダウンロードしてください。
ダウンロードが完了したら、画面下部の Continue with Try Sign-In → ボタンをクリックします。
すると、一番最初の画面に戻ります。次からはXCodeでの操作に戻ります。
3. GoogleService-Info.plist をプロジェクトに追加
先程ダウンロードしたGoogleService-Info.plistをプロジェクトに追加します。
表示すると下記のような設定値が登録されています。
その中から REVERSED_CLIENT_ID と BUNDLE_ID の値をメモします。(BUNDLE_IDの値は最初にメモしたBundle Identifierの値と同じものです)
4. URL Typesの設定
プロジェクトファイル > Targets > Info > URL Types に REVERSED_CLIENT_ID と BUNDLE_ID の値を登録します。
+を2回クリックして、それぞれの値を URL Schemes に設定します。
5. ヘッダファイルの追加
{プロジェクト名}-Bridging-Header.h という名称のヘッダファイルを作成します。
※ 今回サンプルで作ったプロジェクト名はGoogleSignInSampleなので、その場合はGoogleSignInSample-Bridging-Header.hというファイル名になります。
ファイルの中身には
#import <Google/SignIn.h>
と記載します。
そして、 プロジェクトファイル > Targets > Build Settings > Swift Compiler - General 内の Objective-C Bridging Header に先程作成したファイル名、{プロジェクト名}-Bridging-Header.h を記載します。
ここまでで、ひと通りの準備が完了です。
次からコードの実装になります。
実装
下記ページを参考にコードを実装します。
Integrating Google Sign-In into your iOS app | Google Developers
AppDelegate.swift
まずはAppDelegate.swiftにコードを書いていきます。
まずは、 GIDSignInDelegateを受け取れるようにして、
func application(application:, didFinishLaunchingWithOptions:) -> Bool { ... }
内でサインインを初期化するコードを記述します。
// Initialize sign-in var configureError: NSError? GGLContext.sharedInstance().configureWithError(&configureError) assert(configureError == nil, "Error configuring Google services: \(configureError)") GIDSignIn.sharedInstance().delegate = self
GIDSignInDelegateの以下のメソッドを追加します。
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) { ... }
sign()は認証処理の後呼び出されます。
また、GoogleサインインからのリダイレクトURLを受け取る為にopenURLに下記を記述します。
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { return GIDSignIn.sharedInstance().handle(url as URL!, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String!, annotation: options[UIApplicationOpenURLOptionsKey.annotation]) }
サンプル
以下、サンプルコードです。
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Initialize sign-in var configureError: NSError? GGLContext.sharedInstance().configureWithError(&configureError) assert(configureError == nil, "Error configuring Google services: \(configureError)") GIDSignIn.sharedInstance().delegate = self return true } func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { return GIDSignIn.sharedInstance().handle(url as URL!, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String!, annotation: options[UIApplicationOpenURLOptionsKey.annotation]) } 〜 中略 〜 } extension AppDelegate: GIDSignInDelegate { func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) { if let _ = error { // サインインが失敗 } else { // サインインが成功 } } }
ログイン画面を呼び出す処理
ログイン画面を呼び出すViewController側の処理になります。
まずは、GIDSignInUIDelegateを受け取るようにして、
GIDSignIn.sharedInstance().uiDelegate = self
を記述します。
そして、GIDSignInUIDelegateのメソッドとして、
func sign(_ signIn:, present viewController:) { ... }
と
func sign(_ signIn:, dismiss viewController:) { ... }
を記述します。 presentの方はサインイン用のViewControllerが表示される時、 dismissの方は閉じられる時に呼び出されるので、
present側には
present(viewController, animated: true)
dismiss側には
dismiss(animated: true)
を記述します。
そして、ボタンを押したタイミングなどでサインインを実行する
GIDSignIn.sharedInstance().signIn()
を呼び出します。
サンプル
以下、サンプルコードです。
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() GIDSignIn.sharedInstance().uiDelegate = self } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // サインインボタンを押したとき @IBAction func didTapSinginButton(_ sender: AnyObject) { GIDSignIn.sharedInstance().signIn() } } extension ViewController: GIDSignInUIDelegate { func sign(_ signIn: GIDSignIn!, present viewController: UIViewController!) { present(viewController, animated: true) } func sign(_ signIn: GIDSignIn!, dismiss viewController: UIViewController!) { dismiss(animated: true) } }
以上がGoogleサインインを入れるにあたっての(おそらく)最低限の実装になります。
実行イメージ
サインインが実行されると下記のような画面が表示され、
権限を聞かれます。
サインイン後はAppDelegate.swift内のfunc sign(signIn: , didSignInFor user:, withError error:)
が呼び出されます。
尚、画面左上のDone(完了)ボタンを押したり、権限を認めなかったりしても、エラー(失敗)で呼び出されます。
言語について
これらのログイン画面は端末の言語が反映されます。上記画像は英語になってますが、端末の言語設定を日本語にすれば、日本語表示になります。
権限(スコープ)について
Googleサインインには権限があります。
デフォルトだとEmailとprofileの取得になります。
スコープは必要に応じて変更できます。サインインを呼び出す前に、
GIDSignIn.sharedInstance().scopes = [`権限の配列`]
を記載します。
例えばGoogleスプレットシートの権限が必要な場合は
GIDSignIn.sharedInstance().scopes = ["https://www.googleapis.com/auth/spreadsheets"]
のようになります。
権限の値については下記URLをご覧ください。
スコープ一覧
https://developers.google.com/identity/protocols/googlescopes
デフォルトの権限について
また、Emailとprofileはデフォルトで入ってしまっているので、これらの権限が不要な時は、scopesを設定し、shouldFetchBasicProfileをfalseにします。
// Googleスプレットシートの権限のみ GIDSignIn.sharedInstance().scopes = ["https://www.googleapis.com/auth/spreadsheets"] GIDSignIn.sharedInstance().shouldFetchBasicProfile = false
脚注
- 厳密には、公開を制限しないでGoogleAppsScriptを書けば、一部はサインインしなくても使えますが... ↩